<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html lang="zh-CN"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta http-equiv="Content-Language" content="zh-CN"><link href="stylesheet.css" media="all" rel="stylesheet" type="text/css">
<title>WAL 内部</title>
<script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?d286c55b63a3c54a1e43d10d4c203e75"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script>
</head><body class="SECT1">
<div>
<table summary="Header navigation table" width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><th colspan="5" align="center" valign="bottom">PostgreSQL 8.2.3 中文文档</th></tr>
<tr><td width="10%" align="left" valign="top"><a href="wal-configuration.html" accesskey="P">后退</a></td><td width="10%" align="left" valign="top"><a href="wal.html">快退</a></td><td width="60%" align="center" valign="bottom">章27. 可靠性和预写式日志</td><td width="10%" align="right" valign="top"><a href="wal.html">快进</a></td><td width="10%" align="right" valign="top"><a href="regress.html" accesskey="N">前进</a></td></tr>
</table>
<hr align="LEFT" width="100%"></div>
<div class="SECT1"><h1 class="SECT1"><a name="WAL-INTERNALS">27.4. WAL 内部</a></h1>
<p>WAL 是自动打开的。除了要求一些磁盘空间存放 WAL 日志以及一些必要的调节以外(参阅<a href="wal-configuration.html">节27.3</a>)，对管理员没有什么其它要求。</p>
<p> WAL 日志存放在数据目录的 <tt class="FILENAME">pg_xlog</tt> 子目录里，它是作为一个文件段的集合存储的，通常每段 16MB 。每个段又分割成多个页，通常每页 8KB 。日志记录头在 <tt class="FILENAME">access/xlog.h</tt> 里描述；日志内容取决于它记录的事件类型。段文件的名字是递增自然数，从 <tt class="FILENAME">000000010000000000000000</tt> 开始。目前这些数字不能循环使用，不过要把所有可用的数字都用光也需要非常长的时间。</p>
<p>日志位于和主数据库文件不同的另外一个磁盘上会比较好。你可以通过把 <tt class="FILENAME">pg_xlog</tt> 目录移动到另外一个位置(此时必须关闭服务器)，然后在原来的位置创建一个指向新位置的符号链接。</p>
<p> WAL 的目的是确保在数据库记录被修改之前先写日志，但是这个目的有可能被那些向内核谎报成功写入的磁盘驱动器破坏，这时候，它们实际上只是缓冲了数据而并未把数据存储到磁盘上。这种情况下的电源失效仍然可能导致不可恢复的数据崩溃；管理员应该确保保存 PostgreSQL 日志文件的磁盘不会做这种虚假汇报。</p>
<p>在完成一个检查点并且刷新了日志文件之后，检查点的位置就保存在了 <tt class="FILENAME">pg_control</tt> 文件里。因此在需要做恢复的时候，后端首先读取 <tt class="FILENAME">pg_control</tt> 和检查点记录；然后通过从检查点记录里标识的日志位置开始向前扫描执行 REDO 操作。因为数据页的所有内容都保存在检查点之后的第一个页面修改的日志里，所以自检查点以来的所有变化都将被恢复到一个一致的状态。</p>
<p>但是为了处理 <tt class="FILENAME">pg_control</tt> 可能的损坏，我们实际上应该实现对现存日志段的反向读取顺序(从最新到最老)，这样才能找到最后的检查点。这些还没有实现。<tt class="FILENAME">pg_control</tt> 很小(比一个磁盘页小)，因此它出现只写了一部分的问题的概率几乎为零，到目前为止，我们还没有看到不能读取 <tt class="FILENAME">pg_control</tt> 自身的错误。因此，尽管这在理论上是一个薄弱环节，但是实践中 <tt class="FILENAME">pg_control</tt> 似乎并不会出现问题。</p>
</div>
<div>
<hr align="LEFT" width="100%">
<table summary="Footer navigation table" width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><td width="33%" align="left" valign="top"><a href="wal-configuration.html" accesskey="P">后退</a></td><td width="34%" align="center" valign="top"><a href="index.html" accesskey="H">首页</a></td><td width="33%" align="right" valign="top"><a href="regress.html" accesskey="N">前进</a></td></tr>
<tr><td width="33%" align="left" valign="top">WAL 配置</td><td width="34%" align="center" valign="top"><a href="wal.html" accesskey="U">上一级</a></td><td width="33%" align="right" valign="top">回归测试</td></tr>
</table>
</div>
</body></html>